package com.logicbus.dbcp.processor;

import com.anysoft.formula.Expression;
import com.anysoft.formula.FunctionHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;

/**
 * 插件管理器
 * 
 * @author duanyy
 * @since 1.6.3.30
 *
 * @version 1.6.12.45 [20191030] <br>
 * - 支持定制插件; <br>
 *
 * @version 1.6.13.5 [20200605 duanyy] <br>
 * - 增加bind_long,bind_double,bind_auto等指定类型的绑定功能 <br>
 *
 * @version 1.6.15.4 [20211112 duanyy] <br>
 * - 增加bind_array功能 <br>
 */
public class PluginManager implements FunctionHelper {

	/**
	 * a logger of slf4j
	 */
	protected final static Logger LOG = LoggerFactory.getLogger(PluginManager.class);
	/**
	 * 插件注册表
	 */
	protected static Map<String,Class<? extends Plugin>> mapping = new HashMap<String,Class<? extends Plugin>>();

	protected BindedListener bindedListener = null;

	public PluginManager(BindedListener listener){
		bindedListener = listener;
	}

	public static void registerPlugin(String id,Class<? extends Plugin> clazz){
		mapping.put(id,clazz);
	}

	public static Plugin createPlugin(String id,BindedListener bindedListener){
		Class<? extends Plugin> clazz = mapping.get(id);
		if (clazz != null){
			try {
				Constructor<? extends Plugin> constructor = clazz.getConstructor(String.class,BindedListener.class);
				return constructor.newInstance(new Object[]{id,bindedListener});
			} catch (Exception e) {
				LOG.error(String.format("Failed to create plugin %s,reason:%s",id,e.getMessage()));
			}
		}
		return null;
	}

	@Override
	public Expression customize(String funcName) {
		return createPlugin(funcName,this.bindedListener);
	}

	static {
		registerPlugin("not_nvl",Plugin.NotNull.class);
		registerPlugin("bind",Plugin.Bind.class);
		registerPlugin("bind_auto",Plugin.BindAuto.class);
		registerPlugin("bind_long",Plugin.BindLong.class);
		registerPlugin("bind_double",Plugin.BindDouble.class);
		registerPlugin("bind_raw",Plugin.BindRaw.class);
		registerPlugin("bind_array_long",Plugin.BindArrayLong.class);
		registerPlugin("bind_array",Plugin.BindArray.class);
		registerPlugin("uuid",Plugin.UUId.class);
	}
}
